package pl.edu.agh.uddiProxy.dao.hibernate;

import java.sql.SQLException;
import java.util.LinkedList;
import java.util.List;

import javax.persistence.EntityNotFoundException;

import org.hibernate.Criteria;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.criterion.Restrictions;
import org.springframework.dao.DataAccessException;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.springframework.security.userdetails.UserDetailsService;
import org.springframework.security.userdetails.UsernameNotFoundException;

import pl.edu.agh.uddiProxy.dao.UserDAO;
import pl.edu.agh.uddiProxy.types.Authority;
import pl.edu.agh.uddiProxy.types.User;

public class UserHibernateDAO extends HibernateDaoSupport implements UserDAO, UserDetailsService {

	public void create(User user) {
		getHibernateTemplate().save(user);
		getHibernateTemplate().flush();
	}

	public void delete(User user) {
		getHibernateTemplate().delete(user);
		getHibernateTemplate().flush();
	}

	public boolean exists(String login) {
		return loadUserByUsername(login) != null;
	}

	public boolean exists(Long id) {
		return getById(id) != null;
	}

	public List<User> getAll() {
		List<User> result = (List<User>) getHibernateTemplate().execute(
				new HibernateCallback() {
			public Object doInHibernate(final Session session)
					throws SQLException {
				SQLQuery sqlQuery = session.createSQLQuery("SELECT * FROM users");
				sqlQuery.addEntity(User.class);
				return sqlQuery.list();
			}
		});

		return result;
	}

	public List<Long> getAllIds() {
		List<User> entityList = getAll();
		List<Long> idList = new LinkedList<Long>();

		if (entityList == null) {
			return null;
		}

		for (User e : entityList) {
			idList.add(e.getId());
		}

		return idList;
	}

	public User getById(final Long id) {
		if (id == null) {
			throw new EntityNotFoundException("ID is null");
		}

		User result = (User) getHibernateTemplate().execute(new HibernateCallback() {
			public Object doInHibernate(final Session session)
					throws SQLException {
				Criteria criteria = session.createCriteria(User.class);
				criteria.add(Restrictions.eq("id", id));
				return criteria.uniqueResult();
			}
		});


		return result;
	}

	public void update(User user) {
		getHibernateTemplate().update(user);
		getHibernateTemplate().flush();
	}

	public User loadUserByUsername(final String username)
			throws UsernameNotFoundException, DataAccessException {
		if (username == null) {
			throw new EntityNotFoundException("ID is null");
		}

		User result = (User) getHibernateTemplate().execute(new HibernateCallback() {
			public Object doInHibernate(final Session session)
					throws SQLException {
				Criteria criteria = session.createCriteria(User.class);
				criteria.add(Restrictions.eq("username", username));
				return criteria.uniqueResult();
			}
		});


		return result;
	}

	public Authority getAuthority(final String authority) {
		if (authority == null) {
			throw new EntityNotFoundException("ID is null");
		}

		Authority result = (Authority) getHibernateTemplate().execute(new HibernateCallback() {
			public Object doInHibernate(final Session session)
					throws SQLException {
				Criteria criteria = session.createCriteria(Authority.class);
				criteria.add(Restrictions.eq("authority", authority));
				return criteria.uniqueResult();
			}
		});


		return result;
	}
	
}
